import Data.List
import Data.Char

data Policy = Policy Int Int Char deriving (Show)

type Passwords = String

data Entry = Entry Policy Passwords deriving (Show)

readInt :: String -> (Int, String)
readInt s = (number, rest)
    where
        numberString = takeWhile isDigit s
        rest = dropWhile isDigit s
        number = read numberString

-- 2-11 z: zpzzzzzzzzzzz
parseLine :: String -> Entry
parseLine line = 
    Entry (Policy least most targetChar) passwords
    where
        (least, rest1) = readInt line
        (most, rest2) = readInt . tail $ rest1
        targetChar = head . tail $ rest2
        passwords = drop 4 rest2

parseInput :: String -> [Entry] 
parseInput = map parseLine . lines

isEntryValid :: Entry -> Bool
isEntryValid (Entry (Policy least most targetChar) passwords) = 
    (count >= least) && (count <= most)
    where
        count = length . filter (==targetChar) $ passwords

main :: IO ()
main = do
    input <- readFile "./day02/input.txt"
    print . length . filter isEntryValid . parseInput $ input